// -------------------------------
// Graphics coursework (cgRender)
// 
// 3D geometry & math functions
//
// Author:  Ramesh Nair
// Date:    03/03/2004
// -------------------------------

#ifndef _CG_GEOMETRY_H
#define _CG_GEOMETRY_H

#include <math.h>
#include <GL/glut.h>



/* Data structures */



// vector
typedef struct VECTOR3D
{
    float x, y, z;      // vector coordinates
} Vector3D;


// vertex
typedef struct VERTEX3D
{
    Vector3D point;     // vertex coordinates
    Vector3D normal;    // vertex normal
    float u, v;         // texture coordinates
} Vertex3D;


// polygon
typedef struct POLYGON3D
{
    int numVertices;    // no. of vertices
    Vertex3D** v;       // array of pointers to vertices
} Polygon3D;


// texture
typedef struct TEXTURE2D
{
	GLuint id;		// OpenGL texture id
	int width;
	int height;
	int maxcol;		// max. colors
} Texture2D;


// structure to hold 3 rotation angles (degrees)
typedef struct ANGLE3D
{
    GLfloat ax;     // x-axis
    GLfloat ay;     // y-axis
    GLfloat az;     // z-axis
} Angle3D;



/* Math functions */




// -----------------------------------------------
// Calculate euclidian length (magnitude) of 2 vectors
//
// @param   v    	- the vector
// -----------------------------------------------
inline float math_vec_length( Vector3D v )
{
    return sqrtf(
                v.x * v.x +
                v.y * v.y +
                v.z * v.z
                );
}





// -----------------------------------------------
// Calculate dot product of 2 vectors
//
// @param   v1    	- 1st vector
// @param	v2		- 2nd vector
// @return			- the dot product
// -----------------------------------------------
inline float math_vec_dot( Vector3D& v1, Vector3D& v2 )
{
	// [a, b, c]  .  [d, e, f]   	=		ad + be + cf
	return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
}






// -----------------------------------------------
// Calculate cross product of 2 vectors
//
// @param   v1    	- 1st vector
// @param	v2		- 2nd vector
// @param	result	- to hold result
// -----------------------------------------------
inline void math_vec_cross( Vector3D& v1, Vector3D& v2, Vector3D& result )
{
	// [a, b, c]  x  [d, e, f]   	=		[ bf-ce, cd-af, ae-bd ]

	result.x = (v1.y * v2.z) - (v1.z * v2.y);
	result.y = (v1.z * v2.x) - (v1.x * v2.z);
	result.z = (v1.x * v2.y) - (v1.y * v2.x);
}




// -----------------------------------------------
// Normalize a vector
//
// @param   v    	- the vector to normalize
// @param	result	- to hold result vector
// -----------------------------------------------

static void math_vec_normalize( Vector3D& v, Vector3D& result )
{
		// get euclidian length -> sqrt(x^2 + y^2 + z^2)
        float length = math_vec_length(v);

		// avoid divide by 0
		if (length > 0)
		{
			result.x = v.x / length;
			result.y = v.y / length;
			result.z = v.z / length;
		}
}





// -----------------------------------------------
// Calculate forward (viewer) facing normal of a polygon
//
// @param   poly    - the polygon
// @param	result	- to hold result vector
// -----------------------------------------------
static void math_poly_normal_f( Polygon3D& poly, Vector3D& result )
{
    // first line
	Vector3D line1 = { 	poly.v[1]->point.x - poly.v[0]->point.x,
						poly.v[1]->point.y - poly.v[0]->point.y,
						poly.v[1]->point.z - poly.v[0]->point.z
	};

    // second line
	Vector3D line2 = { 	poly.v[1]->point.x - poly.v[2]->point.x,
						poly.v[1]->point.y - poly.v[2]->point.y,
						poly.v[1]->point.z - poly.v[2]->point.z
	};

	// get cross product
    math_vec_cross( line2, line1, result );
}


#endif
